"""
Copyright (c) 2022 Huawei Technologies Co.,Ltd.

openGauss is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:

          http://license.coscl.org.cn/MulanPSL2

THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
"""
"""
Case Type   : 系统内部使用工具
Case Name   : 正在failover/switchover时进行减容
Create At   : 2022/04/13
Owner       : opentestcase023
Description :
    1.集群正在switchover时进行备机减容
    2.集群强制进行failover时进行备机减容
    3.恢复环境
Expect      :
    1.备机减容失败
    2.备机减容失败
    3.恢复成功
History     :
    2022-5-17 opentestcase023 优化用例，根据自动化连跑要求，修改用例为在源库上减容
    2022-9-13 opentestcase023 优化用例，由于研发代码变更，修改用例回显断言
    2022-9-29 opentestcase023 优化用例，优化断言信息
    2023-1-18 opentestcase023 优化用例，更改断言位置，防止用例失败后环境恢复错误
"""
import os
import time
import unittest
from testcase.utils.ComThread import ComThread
from testcase.utils.Common import Common
from testcase.utils.Common import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node
from yat.test import macro
primary_sh = CommonSH('PrimaryDbUser')
Constant = Constant()


@unittest.skipIf(3 != primary_sh.get_node_num(), '非1+2环境不执行')
class Tools(unittest.TestCase):
    def setUp(self):
        self.log = Logger()
        self.common = Common()
        self.log.info(f'----{os.path.basename(__file__)} start----')
        self.primary_root_node = Node('PrimaryRoot')
        self.primary_node = Node('PrimaryDbUser')
        self.standby1_root_node = Node('Standby1Root')
        self.standby1_node = Node('Standby1DbUser')
        self.standby2_root_node = Node('Standby2Root')
        self.standby2_node = Node('Standby2DbUser')
        self.u_name = self.primary_node.ssh_user
        self.ssh_file = os.path.join('/home', self.u_name, 'hostfile')
        num = primary_sh.get_node_num()
        self.assertGreaterEqual(num, 3, "执行失败:节点数量异常，减容不执行")

    def test_gs_dropnode(self):
        text = '----step1:集群正在switchover时进行备机减容 expect:失败----'
        self.log.info(text)
        self.log.info('构建减容命令shell脚本前置条件')
        drop_cmd = f'gs_dropnode -U {self.u_name} -G {self.u_name} ' \
                   f'-h {self.standby2_node.ssh_host}'
        self.log.info(drop_cmd)
        global shell_path
        shell_path = os.path.join('/', 'home', f'{self.u_name}', 'dropnode.sh')
        shell_cmd = f'touch {shell_path};echo -e {drop_cmd} > {shell_path};' \
                    f'chmod 755 {shell_path};cat {shell_path}'
        self.log.info(shell_cmd)
        pri_shell_res = self.primary_root_node.sh(shell_cmd).result()
        sta1_shell_res = self.standby1_root_node.sh(shell_cmd).result()
        self.log.info(pri_shell_res)
        self.log.info(sta1_shell_res)
        self.log.info('在备1上执行switchover操作')
        switch_cmd = f'source {macro.DB_ENV_PATH};' \
                     f'gs_ctl switchover -D {macro.DB_INSTANCE_PATH};'
        session_1 = ComThread(self.common.get_sh_result, args=(
            self.standby1_node, switch_cmd,))
        session_1.setDaemon(True)
        self.log.info('在执行switchover同时执行备2减容')
        execute_cmd = f'source {macro.DB_ENV_PATH};' \
                      f'{shell_path};'
        session_2 = ComThread(self.common.get_sh_result, args=(
            self.primary_node, execute_cmd,))
        session_2.setDaemon(True)
        session_1.start()
        time.sleep(0.0001)
        session_2.start()
        self.log.info('switchover执行结果')
        session_1.join(60)
        session_1_result = session_1.get_result()
        self.log.info(session_1_result)
        self.log.info('备2减容执行结果')
        session_2.join(60)
        session_2_result = session_2.get_result()
        self.log.info(session_2_result)
        self.log.info('刷新配置文件并重启数据库')
        refresh_cmd = f'source {macro.DB_ENV_PATH};' \
                      f'gs_om -t refreshconf;' \
                      f'gs_om -t restart;' \
                      f'gs_om -t status --detail;'
        self.log.info(refresh_cmd)
        refresh_res = self.standby1_node.sh(refresh_cmd).result()
        self.log.info(refresh_res)
        self.assertIn('Successfully started', refresh_res, '刷新配置文件重启失败')
        self.log.info('断言switchover及减容结果')
        self.assertIn(Constant.SWITCH_SUCCESS_MSG, session_1_result,
                      'switchover失败')
        self.assertNotIn('Success to drop the target nodes',
                         session_2_result, '备2减容错误')

        text = '----step2:集群强制failover时执行备机减容 expect:失败'
        self.log.info(text)
        self.log.info('执行failover操作')
        failover_cmd = f'source {macro.DB_ENV_PATH};' \
                       f'gs_ctl failover -D {macro.DB_INSTANCE_PATH};'
        session_3 = ComThread(self.common.get_sh_result, args=(
            self.primary_node, failover_cmd,))
        session_3.setDaemon(True)
        self.log.info('在执行failover同时执行备2减容')
        execute_cmd = f'source {macro.DB_ENV_PATH};' \
                      f'{shell_path};'
        session_4 = ComThread(self.common.get_sh_result, args=(
            self.standby1_node, execute_cmd,))
        session_4.setDaemon(True)
        session_3.start()
        time.sleep(0.0001)
        session_4.start()
        self.log.info('failover执行结果')
        session_3.join(120)
        session_3_result = session_3.get_result()
        self.log.info(session_3_result)
        self.log.info('备2减容执行结果')
        session_4.join(120)
        session_4_result = session_4.get_result()
        self.log.info(session_4_result)
        self.log.info('刷新配置文件并重启数据库')
        refresh_cmd = f'source {macro.DB_ENV_PATH};' \
                      f'gs_ctl restart -D {macro.DB_INSTANCE_PATH} ' \
                      f'-M standby;' \
                      f'gs_om -t refreshconf;' \
                      f'gs_om -t status --detail;'
        self.log.info(refresh_cmd)
        refresh_res = self.standby1_node.sh(refresh_cmd).result()
        self.log.info(refresh_res)
        self.assertIn('Successfully generated dynamic configuration file',
                      refresh_res, '刷新配置文件重启失败')
        self.log.info('断言failover及备机减容')
        self.assertIn(Constant.FAILOVER_SUCCESS_MSG, session_3_result,
                      'switchover失败')
        self.assertNotIn('Success to drop the target nodes',
                         session_4_result, '备2减容错误')

    def tearDown(self):
        text = "----step3：恢复环境 expect:成功----"
        self.log.info(text)
        del_cmd = f"rm -rf {shell_path}"
        self.log.info(del_cmd)
        del_res = self.primary_root_node.sh(del_cmd).result()
        self.log.info(del_res)
        build_cmd = f'source {macro.DB_ENV_PATH};' \
                    f'gs_ctl build -D {macro.DB_INSTANCE_PATH};'
        self.log.info(build_cmd)
        build_res1 = self.standby1_node.sh(build_cmd).result()
        build_res2 = self.standby2_node.sh(build_cmd).result()
        self.log.info(build_res1)
        self.log.info(build_res2)
        self.assertEqual('', del_res, '文件删除失败')
        self.assertIn('server started', build_res1, '重建失败')
        self.assertIn('server started', build_res2, '重建失败')
        self.log.info(f'----{os.path.basename(__file__)} finish----')
